package com.ray.validate.support.aspect;

import com.ray.validate.support.ValidateMethod;
import com.ray.validate.support.utils.ValidateUtil;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.core.annotation.Order;

import java.lang.annotation.Annotation;
import java.lang.reflect.Method;

/**
 * @author bo shen
 * @Description: 请求拦截做统一参数校验
 * @Class: PerformanceAspect
 * @Package com.ray.aspect
 * @date 2018/10/10 18:02
 * @company <p>杭州传化陆鲸科技有限公司</p>
 * @updateRecord time(修改时间)  author(修改人)   desc(修改内容)
 */
@Aspect
@Slf4j
@Order(1001)
public class ValidateAspect implements ApplicationContextAware {

    /**
     * 统一拦截所有 Service请求
     */
    @Pointcut("@annotation(com.ray.validate.support.ValidateMethod)")
    public void validateMethod() {
    }

    @Pointcut("@annotation(org.springframework.validation.annotation.Validated)")
    public void validated() {
    }


    /**
     * @param joinPoint
     * @throws Throwable
     */
    @Around("validateMethod() || validated()")
    public Object validate(ProceedingJoinPoint joinPoint) throws Throwable {
        //当前类型
        Class<?> runClass = joinPoint.getTarget().getClass();
        log.info("类[{}]方法[{}]进行参数校验",runClass.getName(), joinPoint.getSignature().getName());
        MethodSignature joinPointObject = (MethodSignature) joinPoint.getSignature();
        Method method = joinPointObject.getMethod();
        ValidateMethod validateMethod = method.getAnnotation(ValidateMethod.class);
        //判断是否需要进行校验
        Object[] args = joinPoint.getArgs();
        for (Object arg : args) {
            if (validateMethod != null && validateMethod.paramsNullCheck()) {
                ValidateUtil.notNull(arg, "参数不允许为空");
            }
            //单个计算
            for(Annotation annotation : arg.getClass().getAnnotations()){
                ValidateUtil.validateParams(arg,annotation);
            }
            //对象校验
            if (arg != null) {
                //对象校验
                ValidateUtil.validate(arg);
            }
        }
        return  joinPoint.proceed(args);
    }

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        log.info("校验拦截器启动成功");
    }
}
